#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>
#include "camera.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include<termios.h>
#include "serial.h"

int camera;
char *pic_buf;
int len;

struct sockaddr_in address;
int addrlen = sizeof(address);

#define CAMERA_PORT 8080
#define MESSAGE_PORT 8081
#define INFO_PORT 8082

unsigned char command[] = {
        0x00,
        0x01,
        0x02,
        0x03,
        0x04,
        0,
        0,
        0,
        0x08,
        0x09,
        0x0a,
};
unsigned char commandStr[5] = {0xdd, 0x06, 0x24, 0x00, 0x04};

int createServer(int port);

void *handle_message(void *arg);

void *handle_serial(void *arg);

int createServer(int port) {
    int server_fd;
    struct sockaddr_in address;
    // 创建套接字
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
    // 设置服务器地址和端口
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);
    // 设置SO_REUSEADDR选项
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
        perror("Setsockopt failed");
        return 1;
    }
    // 将套接字绑定到指定地址和端口
    if (bind(server_fd, (struct sockaddr *) &address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    // 开始监听连接
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    return server_fd;
}

// 处理客户端连接的线程函数
void *handle_message(void *arg) {

    int readSize;
    char buffer[5] = {0};
    int message_fd = createServer(MESSAGE_PORT);
    printf("message等待连接\n");
    int message_socket = accept(message_fd, (struct sockaddr *) &address, (socklen_t * ) & addrlen);
    printf("message连接成功\n");
    while (1) {
        memset(buffer, 0, sizeof(buffer));
        readSize = read(message_socket, buffer, 5);
        if (readSize > 0) {
            int num = atoi(buffer);
            commandStr[4] = command[num];
            printf("%x\n",commandStr[4]);
            write(serial_fd, commandStr, 5);
            printf("客户端: %s\n", buffer);
            send(message_socket, buffer, strlen(buffer), 0);
        }
    }
    close(message_socket);
    close(message_fd);
    pthread_exit(NULL);
}

// 处理客户端连接的线程函数
//void *handle_camera(void *arg) {
//    struct sockaddr_in address;
//    int addrlen = sizeof(address);
//    int camera_fd = createServer(CAMERA_PORT);
//    printf("camera等待连接\n");
//    int camera_socket = accept(camera_fd, (struct sockaddr *) &address, (socklen_t * ) & addrlen);
//    printf("camera连接成功\n");
//    char buffer[5];
//    while (1) {
//        if (-1 == camera_dequeue(camera, &pic_buf, &len)) {
//            perror("dequeue:");
//            return -1;
//        }
//        sprintf(buffer, "%d", len);
//        send(camera_socket, buffer, 5, 0);
////            printf("服务端: %d\n", len);
//        send(camera_socket, pic_buf, len, 0);
//        camera_enqueue(camera);
//        usleep(33333);
//    }
//    close(camera_fd);
//    close(camera_socket);
//}

void *handle_serial(void *arg) {
    char buffer[5] = {0};
    int info_fd = createServer(INFO_PORT);
    printf("info等待连接\n");
    int info_socket = accept(info_fd, (struct sockaddr *) &address, (socklen_t * ) & addrlen);
    printf("info连接成功\n");
    while (1) {
        unsigned char data[36] = {0};
        read(serial_fd, data, 1);
        if (0xbb == data[0]) {
            memset(buffer, 0, sizeof(buffer));
            read(serial_fd, data + 1, 35);
            sprintf(buffer, "%d %d %d", data[5], data[7], data[20]);
            send(info_socket, buffer, strlen(buffer), 0);
        }
    }
    close(info_fd);
    close(info_socket);
    pthread_exit(NULL);

}

int main() {
    pthread_t message_id;
    pthread_t serial_id;
    //相机初始化
    camera = camera_init("/dev/video0");
    if (-1 == camera_start(camera)) {
        perror("start:");
        return -1;
    }
    //串口初始化
    init_serial_port();
    //serial线程
    if (pthread_create(&serial_id, NULL, handle_serial, NULL)) {
        perror("pthread_create failed");
        exit(EXIT_FAILURE);
    }
    pthread_detach(serial_id);
    //message线程
    if (pthread_create(&message_id, NULL, handle_message, NULL)) {
        perror("pthread_create failed");
        exit(EXIT_FAILURE);
    }
    pthread_detach(message_id);
    int camera_socket;
    int camera_fd = createServer(CAMERA_PORT);
    printf("camera等待连接\n");
    while ((camera_socket = accept(camera_fd, (struct sockaddr *) &address, (socklen_t * ) & addrlen))) {
        printf("camera连接成功\n");
        char buffer[5];
        while (1) {
            if (-1 == camera_dequeue(camera, &pic_buf, &len)) {
                perror("dequeue:");
                return -1;
            }
            sprintf(buffer, "%d", len);
            send(camera_socket, buffer, 5, 0);
//            printf("服务端: %d\n", len);
            send(camera_socket, pic_buf, len, 0);
            camera_enqueue(camera);
            usleep(33333);
        }
    }
    close(camera_fd);
    close(camera_socket);
}